package com.hnx.admin.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.hnx.admin.jwt.JwtProperties;
import com.hnx.admin.jwt.JwtUtil;
import com.hnx.admin.redis.RedisCache;
import com.hnx.admin.security.api.JwtFilter;
import com.hnx.admin.security.utils.SecurityUtil;
import com.hnx.admin.system.domain.dto.user.EmpDTO;
import com.hnx.admin.system.domain.vo.user.UserDetailVO;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

/*
项目名称： core
创 建 人: 倔强的头发
创建日期： 2025/5/26   17:59:40 
描   述：
*/
@Component
public record JwtHandler(JwtUtil jwtUtil, RedisCache redisCache, JwtProperties jwtProperties) implements JwtFilter {
    protected static final long MILLIS_SECOND = 1000;

    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

    private static final Long MILLIS_MINUTE_TEN = 30 * 60 * 1000L;
    @Override
    public void match(HttpServletRequest request) {
        String userKey = jwtUtil.getUserKey(request);
        if(StringUtils.hasText(userKey)) {
            UserDetailVO loginUser = redisCache.getCacheObject(userKey, UserDetailVO.class);
            if (ObjectUtil.isNotEmpty(loginUser) && ObjectUtil.isEmpty(SecurityUtil.getAuthentication())){
                verifyToken(loginUser,userKey);
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
    }
    private void verifyToken(UserDetailVO loginUser,String userKey)
    {
        long expireTime = loginUser.getUserVO().getEmp().getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
        {
            refreshToken(loginUser,userKey);
        }
    }
    /**
     * 刷新令牌有效期
     *
     * @param loginUser 登录信息
     */
    public void refreshToken(UserDetailVO loginUser,String userKey)
    {
        EmpDTO emp = loginUser.getUserVO().getEmp();
        emp.setLoginTime(System.currentTimeMillis());
        emp.setExpireTime(emp.getLoginTime() + jwtProperties.getExpireTime() * MILLIS_MINUTE);
        redisCache.setCacheObject(userKey, loginUser, jwtProperties.getExpireTime(), TimeUnit.MINUTES);
    }
}
